<?php
class RDFIOEquivalentURIHandler {

    protected $m_advwikititleuris;
    protected $m_nsprefixes;
    protected $m_tripleindex;
    protected $m_usensprefixes;
    protected $m_store;

    function __construct( $advwikititleuris = '' ) {
        global $rdfiogPropertiesToUseAsWikiTitle, $rdfiogUsePseudoNamespaces;

        if ( !empty( $rdfiogUsePseudoNamespaces ) ) {
            $this->m_usensprefixes = $rdfiogUsePseudoNamespaces;
        } else {
            $this->m_usensprefixes = false;
        }

        if ( !empty( $rdfiogPropertiesToUseAsWikiTitle ) ) {
            $this->m_advwikititleuris = $rdfiogPropertiesToUseAsWikiTitle;
        } else {
            $this->m_advwikititleuris = array(
            	'http://semantic-mediawiki.org/swivt/1.0#page',
            	'http://www.w3.org/2000/01/rdf-schema#label',
            	'http://purl.org/dc/elements/1.1/title',
            	'http://www.w3.org/2004/02/skos/core#preferredLabel',
            	'http://xmlns.com/foaf/0.1/name'
            	);
        }

        $this->m_store = new RDFIOStore();
    }

    public function setNSPrefixes( $nsprefixmapping ) {
        $this->m_nsprefixes = $nsprefixmapping;
    }

    public function setTripleIndex( $tripleindex ) {
        $this->m_tripleindex = $tripleindex;
    }

    /**
     * Converts a (full) URI into a string suitable for use as wiki title
     * @param string $uri
     * @return string
     */
    public function getWikiTitleForURI( $uri ) {
        global $rdfiogUsePseudoNamespaces;

        if ( !$this->isURIResolverURI( $uri ) && !$this->isArcUntitledNode( $uri ) ) {
            $titleByStoredOriginalUri = $this->getWikiTitleByStoredOriginalUri( $uri );
        }

        if ( $titleByStoredOriginalUri != '' ) {
            $wikititle = $titleByStoredOriginalUri;
        } else {
            $advTitle = $this->getAdvancedWikiTitle( $uri );
            if ( $advTitle != '' ) {
                $wikititle = $advTitle;
            } else if ( $rdfiogUsePseudoNamespaces ){
                $wikititle = $this->abbreviateNSFromURI( $uri );
            } else {
                $wikititle = $this->extractLabelFromURI( $uri );
            }
            $wikititle = $this->sanitizeWikiTitle( $wikititle );
        }
        if ( !$this->isURL( $wikititle ) ) {
            $wikititle = ucfirst( $wikititle );
        }
        return $wikititle;
    }

    public function getWikiTitleByStoredOriginalUri( $uri ) {
        $origuri = $this->m_store->getWikiTitleByOriginalURI( $uri );
        $origuri = str_replace( '-3A', ':', $origuri );
        $origuri = str_replace( '-3F', '?', $origuri );
        $origuri = str_replace( '-2D', '-', $origuri );
        return $origuri;
    }

    public function convertOutData( $outdata ) {
        $outdata = str_replace( 'http://localhost/smw/index.php/Special:URIResolver/Http-3A//', 'http://', $outdata );
        # $outdata = str_replace( '-3A', ':', $outdata );
        # $outdata = str_replace( '-3F', '?', $outdata );
        // The plan:
        // 1. Get to know which ns corresnponds to http://localhost/smw/index.php/Special:URIResolver/
        //    and remove that namespace from all data.
        // 2. Remove all instances of http://localhost/smw/index.php/Special:URIResolver/
        // 3. Expand prefixes
        // 4. Expand advanced wiki titles
        //    - This is a bit tricky. How to know the original URI?
        //      Only way seems be to store it explicitly in the wiki article (xml:ified, probably)
        return $outdata;
    }

    /**
     * Convert a namespace into its corresponding prefix, using prefix definitions
     * submitted in imported RDF/XML, if available.
     * @param string $ns
     * @return string
     */
    function getPrefixForNS( $ns ) {
        // Namespace prefis definitions are stored in the 'nsp' array
        // of the (RDF/XML) parser object, since import.
        $prefix = $this->m_nsprefixes[$ns];
        if ( $prefix == '' ) $prefix = $ns;
        return $prefix;
    }

    /**
     * Remove characters which don't work in wiki titles
     * @param string $uri
     */
    public function sanitizeWikiTitle( $title ) {
        # $uri = SMWExporter::encodeURI( $uri );
        // Optimally we should rely on SMWExporter::encodeURI
        // but seems we cannot. TODO: Think through if this is true
        $title = str_replace( '#', '-23', $title );
        $title = str_replace( '[', '', $title );
        $title = str_replace( ']', '', $title );
        # $title = preg_replace( '/[\[\]]/', '', $title );
        return $title;
    }

    /**
     * Remove characters which don't work in smw values
     * @param string $uri
     */
    public function sanitizeSMWValue( $value ) {
        # $uri = SMWExporter::encodeURI( $uri );
        // Optimally we should rely on SMWExporter::encodeURI
        // but seems we cannot. TODO: Think through if this is true
        $value = str_replace( '[', '', $value );
        $value = str_replace( ']', '', $value );
        return $value;
    }

    /**
     * Use a "natural language" property, such as dc:title or similar, as wiki title
     * @param string $subject
     * @return string
     */
    private function getAdvancedWikiTitle( $subject ) {
        // Looks through, in order, the uri:s in $this->m_advwikititleuris
        // to see if any of them is set for $subject. if so, return corresponding
        // value as title.
        foreach ( $this->m_advwikititleuris as $advtitleuri ) {
            $titleuri = $this->m_tripleindex[$subject][$advtitleuri][0]['value'];
            $title = $this->abbreviateNSFromURI( $titleuri );
            if ( $title != '' ) {
                break;
            }
        }
        return $title;
    }

    public function abbreviateNSFromURI( $uri ) {
        $uriParts = $this->splitURI( $uri );
        if ( $uriParts[1] == '' ) {
            $uri = $uriParts[0];
        } else if ( substr($uriParts[0], 0, 1) == '_' ) {
            // Change ARC:s default "random string", to indicate more clearly that
            // it lacks title
            $uri = str_replace('arc','untitled',$uriParts[1]);
        } else if ( substr($uriParts[0], -1) == ':' ) {
            // Don't add another colon
            $uri = $this->getPrefixForNS($uriParts[0]) . $uriParts[1];
        } else {
            $nsprefix = $this->getPrefixForNS($uriParts[0]);
            if ( !$this->m_usensprefixes || substr($nsprefix, 0, 4) == 'http' ) {
                $uri = $uriParts[1];
            } else {
                $uri = $this->getPrefixForNS($uriParts[0]) . ':' . $uriParts[1];
            }
        }
        return $uri;
    }
    
    // TODO: This is a duplication of a method in RDFImporter.php. Fix this!
    function isURIResolverURI( $uri ) {
        $isURIResolverURI = ( preg_match( '/Special:URIResolver/', $uri, $matches ) > 0 );
        return $isURIResolverURI;
    }
    
    // TODO: This is a duplication of a method in RDFImporter.php. Fix this!
    function isArcUntitledNode( $uri ) {
        $isURIResolverURI = ( preg_match( '/^Arc/', $uri, $matches ) > 0 );
        $isURIResolverURI2 = ( preg_match( '/_:arc/', $uri, $matches ) > 0 );
        return ( $isURIResolverURI || $isURIResolverURI2 );
    }
    
    function isURL( $text ) {
        $isURL = ( preg_match( '/^http:/', $uri, $matches ) > 0 );
        return $isURL;
    }
    

    public function extractLabelFromURI( $uri ) {
        $uriparts = $this->splitURI( $uri );
        $basepart = $uriparts[0];
        $localpart = $uriparts[1];
        if ( $localpart[1] != '' ) {
            return $localpart; 
        } else {
            return $basepart;
        }
    }

    /**
     * Customized version of the splitURI($uri) of the ARC2 library ( http://arc.semsol.org )
     */
    private function splitURI($v) {
        global $rdfiogBaseURIs;
        /* ADAPTED FROM ARC2 WITH SOME MODIFICATIONS
         * the following namespaces may lead to conflated URIs,
         * we have to set the split position manually
         */
        if (strpos($v, 'www.w3.org')) {
            $specials = array(
        'http://www.w3.org/XML/1998/namespace',
        'http://www.w3.org/2005/Atom',
        'http://www.w3.org/1999/xhtml',
            );
            if ( $rdfiogBaseURIs != '' ) {
                $specials = array_merge( $specials, $rdfiogBaseURIs );
            }
            foreach ($specials as $ns) {
                if (strpos($v, $ns) === 0) {
                    $local_part = substr($v, strlen($ns));
                    if (!preg_match('/^[\/\#]/', $local_part)) {
                        return array($ns, $local_part);
                    }
                }
            }
        }
        /* auto-splitting on / or # */
        //$re = '^(.*?)([A-Z_a-z][-A-Z_a-z0-9.]*)$';
        if (preg_match('/^(.*[\/\#])([^\/\#]+)$/', $v, $m)) return array($m[1], $m[2]);
        /* auto-splitting on last special char, e.g. urn:foo:bar */
        if (preg_match('/^(.*[\:\/])([^\:\/]+)$/', $v, $m)) return array($m[1], $m[2]);
        return array($v, '');

    }

    /**
     * Prints out the structure of an array enclosed in <pre> tags. Used for debugging
     * @param array $arrayToShow
     * @param string $title
     */
    private function showArray( $arrayToShow, $title ) {
        echo "<h2>$title</h2><pre style=\"font-size: 12px; font-weight: bold;\">";
        print_r( $arrayToShow );
        echo "</pre>";
    }

}